#!/usr/bin/python
# -*-coding:Utf-8 -*

import socket

import spectateur as m_spectateur


class Joueur :
	"""Classe représentant un joueur avec :
	- la partie
	- la socket
	- l'adresse IP
	- le pseudo
	- le score
	- si le joueur est dessinateur pour ce round
	- si le joueur a signalé un abus pour ce round
	- si le joueur est devenu un spectateur"""
	
	def __init__(self, p_socket, p_adresse) :
		self.partie = None
		self.socket = p_socket
		self.adresse = "{}:{}".format(p_adresse[0], p_adresse[1])
		self.pseudo = ""
		self.score = 0
		self.est_dessinateur = False
		self.a_signale_un_abus = False
		self.spectateur = False
	
	
	def envoyer(self, p_message) :
		self.socket.sendall(p_message)
	
	
	def deconnecter(self) :
		try :
			self.socket.close()
		except :
			print("Socket du joueur [{}] {} déjà fermée.".format(self.adresse, self.pseudo))
	
	
	def augmenter_score(self, p_score) :
		self.score += int(p_score)
	
	
	def nouveau_tour(self) :
		self.est_dessinateur = False
		self.a_signale_un_abus = False
	
	
	def routine(self, p_partie) :
		self.partie = p_partie
		stop = False
		try :
			# Tant qu'on n'a pas attribué un pseudo unique au client
			while True :
				message = self.socket.recv(1024)
				if not message or len(message.strip()) == 0 :
					stop = True
					break
				print("[{}] {} -> \"{}\"".format(self.adresse, self.pseudo, message.strip()))
				message_args = message.split("/")
				if len(message_args) >= 2 and message_args[0] == "CONNECT" :
					self.partie.verrou.acquire()
					# Si le joueur a pu être intégré à la partie
					if self.partie.integrer_joueur(self, message_args[1].strip()) :
						self.partie.verrou.release()
						break
					else :
						self.partie.verrou.release()
						self.envoyer("ACCESSDENIED/\n")
				elif len(message_args) >= 3 and message_args[0] == "LOGIN" :
					message_args = message.split("/", 2)
					self.partie.verrou.acquire()
					# Si le joueur a pu être intégré à la partie
					if self.partie.login(self, message_args[1].strip(), message_args[2].strip().rstrip("/").strip()) :
						self.partie.verrou.release()
						break
					else :
						self.partie.verrou.release()
						self.envoyer("ACCESSDENIED/\n")
				elif len(message_args) >= 3 and message_args[0] == "REGISTER" :
					message_args = message.split("/", 2)
					self.partie.verrou.acquire()
					# Si le joueur a pu être intégré à la partie
					if self.partie.register(self, message_args[1].strip(), message_args[2].strip().rstrip("/").strip()) :
						self.partie.verrou.release()
						break
					else :
						self.partie.verrou.release()
						self.envoyer("ACCESSDENIED/\n")
				elif len(message_args) >= 1 and message_args[0] == "SPECTATOR" :
					adresse_tmp = self.adresse.split(":")
					self.partie.verrou.acquire()
					self.partie.nouveau_spectateur(m_spectateur.Spectateur(self.socket, adresse_tmp))
					self.partie.verrou.release()
					self.spectateur = True
					return
				elif message_args[0] == "EXIT" :
					stop = True
					break
				else :
					self.envoyer("ACCESSDENIED/\n")
			# Ecoute du client
			while not stop :
				message = self.socket.recv(1024)
				if not message or len(message.strip()) == 0 :
					stop = True
					break
				print("[{}] {} -> \"{}\"".format(self.adresse, self.pseudo, message.strip()))
				message_args = message.split("/")
				if len(message_args) >= 2 and message_args[0] == "TALK" :
					self.partie.verrou.acquire()
					self.partie.talk(self, message_args[1].strip())
					self.partie.verrou.release()
					continue
				if not self.est_dessinateur :
					if len(message_args) >= 2 and message_args[0] == "GUESS" :
						self.partie.verrou.acquire()
						self.partie.guess(self, message_args[1].strip())
						self.partie.verrou.release()
						continue
					elif len(message_args) >= 2 and message_args[0] == "CHEAT" and not self.a_signale_un_abus :
						self.partie.verrou.acquire()
						self.partie.cheat(self, message_args[1].strip())
						self.partie.verrou.release()
						continue
					elif message_args[0] == "EXIT" :
						stop = True
						break
				else :
					if len(message_args) >= 5 and message_args[0] == "SET_LINE" :
						# On s'assure que chaque coordonnée est un entier
						try :
							int(message_args[1].strip())
							int(message_args[2].strip())
							int(message_args[3].strip())
							int(message_args[4].strip())
						except :
							message_erreur = "Coordonnées d'un ou plusieurs points incorrectes."
							print(message_erreur)
							self.envoyer("LISTEN/(broadcast)/ERREUR : {}\n".format(message_erreur))
							continue
						self.partie.verrou.acquire()
						self.partie.set_line(self, message_args[1].strip(), message_args[2].strip(), message_args[3].strip(), message_args[4].strip())
						self.partie.verrou.release()
						continue
					elif len(message_args) >= 4 and message_args[0] == "SET_COLOR" :
						# On s'assure que chaque couleur est un entier
						try :
							int(message_args[1].strip())
							int(message_args[2].strip())
							int(message_args[3].strip())
						except :
							message_erreur = "Code couleur incorrect."
							print(message_erreur)
							self.envoyer("LISTEN/(broadcast)/ERREUR : {}\n".format(message_erreur))
							continue
						self.partie.verrou.acquire()
						self.partie.set_color(message_args[1].strip(), message_args[2].strip(), message_args[3].strip())
						self.partie.verrou.release()
						continue
					elif len(message_args) >= 2 and message_args[0] == "SET_SIZE" :
						# On s'assure que la taille est un entier
						try :
							int(message_args[1].strip())
						except :
							message_erreur = "Taille du trait incorrecte."
							print(message_erreur)
							self.envoyer("LISTEN/(broadcast)/ERREUR : {}\n".format(message_erreur))
							continue
						self.partie.verrou.acquire()
						self.partie.set_size(message_args[1].strip())
						self.partie.verrou.release()
						continue
					elif message_args[0] == "PASS" :
						self.partie.verrou.acquire()
						self.partie.passed()
						self.partie.verrou.release()
						continue
					if len(message_args) >= 9 and message_args[0] == "COURBE" :
						# On s'assure que chaque coordonnée est un entier
						try :
							int(message_args[1].strip())
							int(message_args[2].strip())
							int(message_args[3].strip())
							int(message_args[4].strip())
							int(message_args[5].strip())
							int(message_args[6].strip())
							int(message_args[7].strip())
							int(message_args[8].strip())
						except :
							message_erreur = "Coordonnées d'un ou plusieurs points incorrectes."
							print(message_erreur)
							self.envoyer("LISTEN/(broadcast)/ERREUR : {}\n".format(message_erreur))
							continue
						self.partie.verrou.acquire()
						self.partie.courbe(self, message_args[1].strip(), message_args[2].strip(), message_args[3].strip(), message_args[4].strip(), message_args[5].strip(), message_args[6].strip(), message_args[7].strip(), message_args[8].strip())
						self.partie.verrou.release()
						continue
					elif message_args[0] == "EXIT" :
						stop = True
						break
		except :
			if not self.spectateur :
				print("Déconnexion du joueur [{}] {}...".format(self.adresse, self.pseudo))
		finally :
			self.partie.verrou.acquire()
			self.partie.retirer_joueur(self)
			self.partie.verrou.release()
			# Si le joueur est devenu un spectateur, on ne ferme pas la socket
			if not self.spectateur :
				self.deconnecter()
				print("Le joueur [{}] {} s'est déconnecté.".format(self.adresse, self.pseudo))
